package com.ce.pub.process.logic.impl;

import java.io.InputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.dao.DataAccessException;

import com.ce.framework.datamaintain.dao.po.AbstractPO;
import com.ce.framework.datamaintain.logic.IBaseLogic;
import com.ce.framework.datamaintain.logic.ISQLMapper;
import com.ce.framework.exception.AppException;
import com.ce.framework.exception.DaoException;
import com.ce.framework.util.BeanAccessUtil;
import com.ce.framework.util.StringUtil;
import com.ce.pub.process.logic.ProcessDealService;
import com.ce.sys.login.model.User;
import com.ce.sys.person.dao.po.SysPerson;
import com.ce.sys.role.dao.po.SysRole;
import com.ce.util.DbUtil;


public class ProcessDealServiceImpl implements ProcessDealService {
	private IBaseLogic baselogic;
	private RepositoryService repositoryService;
	private RuntimeService runtimeService;
	private TaskService taskService;
	private HistoryService historyService;
	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:启动流程
	* 方法的参数和返回值: 
	* @param entity
	* @param definitionKey
	* @throws AppException 
	* @return
	*/
	public void doStart(AbstractPO entity, String definitionKey)
			throws AppException {
		entity.setStatus(1);
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("model", entity);
		ProcessInstance processInstance = runtimeService
				.startProcessInstanceByKey(definitionKey, entity.getVcId(),
						variables);
		entity.setProcessInstanceId(processInstance.getId());
		baselogic.updatePo(entity);
		Task task = taskService.createTaskQuery()
				.processInstanceId(processInstance.getId()).singleResult();
		taskService.complete(task.getId());
	}
	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:启动流程
	* 方法的参数和返回值: 
	* @param vcId
	* @param po
	* @param definitionKey
	* @throws AppException 
    * @throws DataAccessException 
	* @throws DaoException 
	* @return
	*/
	@SuppressWarnings("unchecked")
	public void startProcess(String[] vcId, AbstractPO po, String definitionKey)
			throws DataAccessException, AppException, DaoException {
		StringBuffer sql = new StringBuffer("From " + po.getClass().getName()
				+ " po where po.vcId in(");
		for (int i = 0; i < vcId.length; i++) {
			if (i == 0) {
				sql.append("'" + vcId[i] + "'");
			} else {
				sql.append(",'" + vcId[i] + "'");
			}
		}
		sql.append(")");

		List<AbstractPO> list = (List<AbstractPO>) baselogic.searchByHql(sql
				.toString());
		for (AbstractPO entity : list) {
			entity.setStatus(1);
			Map<String, Object> variables = new HashMap<String, Object>();
			variables.put("model", entity);
			ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(definitionKey, entity.getVcId(),variables);
			entity.setProcessInstanceId(processInstance.getId());
			
			Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
			taskService.complete(task.getId());
			//获取流程下一流程节点
			Task nextTask=taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
			entity.setStatusInfo(nextTask.getName());
			baselogic.updatePo(entity);
		}

	}

	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:查询待办任务记录id
	* 方法的参数和返回值: 
	* @return
	* @throws AppException
	* @throws DataAccessException
	*/
	public String findTodoTasksId(List<Task> tasks) throws DataAccessException,AppException {
		StringBuffer tasksId = new StringBuffer("");
		// 根据流程的业务ID查询实体主键
		if (!tasks.isEmpty()) {
			tasksId.append("(");
			int usefulKey = 0;
			for (Task task : tasks) {
				String processInstanceId = task.getProcessInstanceId();
				ProcessInstance processInstance = runtimeService
						.createProcessInstanceQuery()
						.processInstanceId(processInstanceId).active()
						.singleResult();
				String businessKey = processInstance.getBusinessKey();
				if (businessKey == null) {
					continue;
				} else {
					usefulKey++;
				}
				if (usefulKey == 1) {
					tasksId.append("'" + businessKey + "'");
				} else {
					tasksId.append(",'" + businessKey + "'");
				}
			}
			tasksId.append(")");
		} else {
			tasksId.append("('')");
		}
		return tasksId.toString();
	}

	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:查询待办任务
	* 方法的参数和返回值: 
	* @return
	* @throws AppException
	* @throws DataAccessException
	*/
	public List<Task> findTodoTasks(String userId, String definitionKey)throws DataAccessException, AppException {
		List<Task> tasks = new ArrayList<Task>();
		// 候选人是当前用户
		TaskQuery userQuery = taskService.createTaskQuery()
				.processDefinitionKey(definitionKey).taskCandidateUser(userId)
				.active().orderByTaskId().desc().orderByTaskCreateTime().desc();
		List<Task> userTasks = userQuery.list();

		// 候选组等于当前用户的职位(回头可以修改activiti源码 or group)
		List<SysRole> roles = this.getRolesByUser(userId);
		List<String> inRoles = new ArrayList<String>();
		for (SysRole role : roles) {
			inRoles.add(role.getVcName());
		}
		tasks.addAll(userTasks);
		if(!inRoles.isEmpty()){
			TaskQuery groupQuery = taskService.createTaskQuery()
					.processDefinitionKey(definitionKey)
					.taskCandidateGroupIn(inRoles).active().orderByTaskId().desc()
					.orderByTaskCreateTime().desc();
			List<Task> groupTasks = groupQuery.list();
			tasks.addAll(groupTasks);
		}
		return tasks;
	}
	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:执行任务
	* 方法的参数和返回值: 
	* @param transition：seqenceFlow的名字,用于驳回
	* @param task：任务
	* @param model: 业务数据
	* @param currentUser：申请人
	* @param comment：审批意见
	* @return
	 * @throws AppException 
	*/
	public void doTask(String transition, Task task, Object model,String comment) throws AppException {
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("isPass", transition);
		AbstractPO m = (AbstractPO) model;
		AbstractPO entity = (AbstractPO)baselogic.getPOByPk(m.getClass().getName(), m.getVcId());
		//处理驳回修改重新提交申请
		if ("提交申请".equals(task.getName())) {
			BeanAccessUtil.copyNoCopyNullProperty(model, entity);
			variables.put("model", entity);
		}
		//写入审批意见
		if (StringUtil.isNotBlank(comment)) {
			//修改activiti源码重载的方法
			taskService.addComment(task.getId(), task.getProcessInstanceId(), User.getUserName(), transition, comment);
		}
		//完成当前流程
		taskService.claim(task.getId(), User.getUserId());
		taskService.complete(task.getId(), variables);
		//进入下一流程获取流程节点
		Task nextTask=taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
		if(nextTask!=null){
			//驳回申请处理
			if("提交申请".equals(nextTask.getName())){
				entity.setStatusInfo("调整申请");
			}else{
				entity.setStatusInfo(nextTask.getName());
			}
		}else{//流程结束
			entity.setStatus(9);
			entity.setStatusInfo("审批通过");
		}
		this.baselogic.updatePo(entity);	
	}
	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:查询流程实例的审批意见
	* 方法的参数和返回值: 
	* @param processInstance
	* @return
	*/
	public List<Map<String, Object>> getComments(String processInstanceId) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		List<Comment> comments=taskService.getProcessInstanceComments(processInstanceId);
		for(Comment comment:comments){
			Map<String, Object> map = new HashMap<String, Object>();
			HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery()
					.taskId(comment.getTaskId()).singleResult();
			map.put("time", comment.getTime());
			map.put("taskName", taskInst.getName());
			map.put("userName", comment.getUserId());
			map.put("action", comment.getAction());
			map.put("message", comment.getFullMessage());
			list.add(map);
		}
		return list;
	}
	public InputStream getProcessTaskImg(String processInstanceId){
		 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
	     BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
	     List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
	     // 不使用spring请使用下面的两行代码
	     ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();
	     Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());

	     // 使用spring注入引擎请使用下面的这行代码
	     //Context.setProcessEngineConfiguration(processEngine.getProcessEngineConfiguration());

	     InputStream imageStream = ProcessDiagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds);
		 return imageStream;
	}
	/**
	* 开发人：andy
	* 开发日期: 2014-2-26
	* 功能描述:获取部门及角色人员或获取角色人员
	* 方法的参数和返回值: 
	* @return
	*/
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<SysPerson> getPersonsByDepAndRole(String depId, String roleName) {
		StringBuffer sql = new StringBuffer(
				"select * from sys_t_person t1 where t1.vc_del$flag=0");
		if (StringUtil.isNotBlank(depId)) {
			sql.append(" and t1.vc_org$id='" + depId + "'");
		}
		if (StringUtil.isNotBlank(roleName)) {
			sql.append(" and t1.vc_id in (")
					.append("select t2.vc_user$id from sys_t_account$role t2,sys_t_role t3 where t2.vc_role$id=t3.vc_id and t3.vc_name='"
							+ roleName + "'").append(" and t3.vc_del$flag=0)");
		}

		ISQLMapper mapper = new ISQLMapper() {
			public Object fromSQLQuery(ResultSet rs, int row) {
				SysPerson person = new SysPerson();
				try {
					person.setVcId(rs.getString("VC_ID"));
					person.setVcName(rs.getString("VC_NAME"));
				} catch (SQLException e) {
					e.printStackTrace();
				}

				return person;
			}
		};
		List<SysPerson> list = DbUtil.executeSqlQuery(sql.toString(), mapper);
		return list;
	}
		/**
		* 开发人：andy
		* 开发日期: 2014-2-26
		* 功能描述:获取人员角色
		* 方法的参数和返回值: 
		* @return
		*/
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<SysRole> getRolesByUser(String userId) {
		StringBuffer sql = new StringBuffer(
				"select t1.vc_id,t1.vc_name from sys_t_role t1,sys_t_account$role t2 where t1.vc_id=t2.vc_role$id ")
				.append(" and t2.vc_user$id='" + userId
						+ "' and t1.vc_del$flag=0 ");
		ISQLMapper mapper = new ISQLMapper() {
			public Object fromSQLQuery(ResultSet rs, int row) {
				SysRole role = new SysRole();
				try {
					role.setVcId(rs.getString("VC_ID"));
					role.setVcName(rs.getString("VC_NAME"));
				} catch (SQLException e) {
					e.printStackTrace();
				}
				return role;
			}
		};
		List<SysRole> list = DbUtil.executeSqlQuery(sql.toString(), mapper);
		return list;
	}

	public void setBaselogic(IBaseLogic baselogic) {
		this.baselogic = baselogic;
	}
	
	

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}
	public void setRuntimeService(RuntimeService runtimeService) {
		this.runtimeService = runtimeService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

}
